package Matrix;
import java.util.Arrays;
import java.util.Scanner;

public abstract class GenMatrix<E extends Number>{
    private int col,row;
    private E[][] mat;
    public GenMatrix(int column,int row){
        this(column,row,true);
    }
    public GenMatrix(int c,int r,boolean bool){
        col=c;
        row=r;
        mat=(E[][])new Number[row][col];
        if(bool)readGenMatrix();
    }
    public GenMatrix(int c,int r,E[]array){
        this(c,r,false);
        for(int i=0;i<row;++i){
            for(int j=0;j<col;++j){
                mat[i][j]=array[i*col+j];
            }
        }
    }
    public GenMatrix(int c,int r,E[][]array){
        this(c,r,false);
        for(int i=0;i<row;++i){
            for(int j=0;i<col;++j){
                mat[i][j]=array[i][j];
            }
        }
    }
    public GenMatrix(GenMatrix<E> m){
        this(m.col,m.row,false);
        for(int i = 0;i<row;++i){
            if (col >= 0) System.arraycopy(m.mat[i], 0, mat[i], 0, col);
        }
    }
    public void readGenMatrix(){
        for(int i=0;i<row;++i){
            for(int j=0;j<col;++j){
                mat[i][j]=readElem();
            }
        }
    }
    public abstract E readElem();
    //    public GenMatrix(int c,int t,)
    public GenMatrix<E> add(GenMatrix<E> m){
        for(int i=0;i<row;++i){
            for(int j=0;j<col;++j){
                mat[i][j]=this.addElem(mat[i][j],m.mat[i][j]);
            }
        }return this;
    }
    protected abstract E addElem(E lh,E rh);
    public GenMatrix<E> transfer(){
        E[][] matr=(E[][])new Number[col][row];
        for(int i=0;i<col;++i){
            for(int j=0;j<row;++j){
                matr[i][j]=mat[j][i];
            }
        }
        mat=matr;
        int temp=col;
        col=row;
        row=temp;
        return this;
    }
    public void showGenMatrix(){
        for(int i=0;i<row;++i){
            for(int j=0;j<col;++j){
                System.out.print(mat[i][j]+"\t");
            }
            System.out.println();
        }
        System.out.println();
    }
    public E[] getCol(int i) throws Except {
        if(i>=col)throw new Except("column not exists");
        E[] elems=(E[])new Number[row];
        for(int j=0;j<row;++j){
            elems[j]=mat[j][i];
        }
        return elems;
    }
    public E[] getRow(int row) throws Except {
        if(row>=col)throw new Except("row not exists");
        E[] elems= (E[]) new Number[col];
        for(int j=0;j<col;++j){
            elems[j]=mat[row][j];
        }
        return elems;
    }
    public void setPos(int r,int c,E val) throws Except {
        if(r>=row||c>=col)throw new Except("position not exists");
        mat[r][c]=val;
    }
    public static void main(String[]args){

        Integer[] integers=new Integer[12];
        for(int i=0;i<12;++i){
            integers[i]=i+5;
        }
        GenMatrix<Integer> intM=new GenMatrix<Integer>(3,4,integers) {
            @Override
            public Integer readElem() {
                return new Scanner(System.in).nextInt();
            }

            @Override
            protected Integer addElem(Integer lh, Integer rh) {
                return lh+rh;
            }
        };
        GenMatrix<Integer>gi=intM;
        intM.showGenMatrix();
        try {
            Number[] e = intM.getCol(2);
            Arrays.stream(e).forEach(System.out::println);
            Number[] ep=intM.getRow(2);
            Arrays.stream(ep).forEach(System.out::println);
        } catch (Except except) {
            except.printStackTrace();
        }
        intM.transfer().showGenMatrix();
        gi.showGenMatrix();
    }
}
class intMatrix extends GenMatrix<Integer>{
    intMatrix(int c,int r){
        super(c,r);
    }
    @Override
    public Integer readElem() {
        return new Scanner(System.in).nextInt();
    }

    @Override
    protected Integer addElem(Integer lh, Integer rh) {
        return lh+rh;
    }
}
